package com.bi.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.bi.common.Result;
import com.bi.entity.DataComponent;
import com.bi.entity.DataComponentField;
import com.bi.service.DataComponentFieldService;
import com.bi.service.DataComponentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * 数据组件控制器
 * 
 * @author BI Platform Team
 * @since 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/data-components")
@RequiredArgsConstructor
@Tag(name = "数据组件管理", description = "数据组件的创建、配置、查询等功能")
public class DataComponentController {

    private final DataComponentService dataComponentService;
    private final DataComponentFieldService dataComponentFieldService;

    @GetMapping
    @Operation(summary = "分页查询数据组件", description = "根据条件分页查询数据组件列表")
    public Result<IPage<DataComponent>> getComponentPage(
            @Parameter(description = "当前页", example = "1") @RequestParam(defaultValue = "1") long current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") long size,
            @Parameter(description = "组件名称") @RequestParam(required = false) String name,
            @Parameter(description = "组件类型") @RequestParam(required = false) String type,
            @Parameter(description = "组件状态") @RequestParam(required = false) String status,
            @Parameter(description = "数据源类型") @RequestParam(required = false) String dataSourceType,
            @Parameter(description = "创建人") @RequestParam(required = false) String creator) {
        
        Map<String, Object> params = Map.of(
            "name", name != null ? name : "",
            "type", type != null ? type : "",
            "status", status != null ? status : "",
            "dataSourceType", dataSourceType != null ? dataSourceType : "",
            "creator", creator != null ? creator : ""
        );
        
        IPage<DataComponent> page = dataComponentService.getComponentPage(current, size, params);
        return Result.success(page);
    }

    @GetMapping("/{id}")
    @Operation(summary = "获取数据组件详情", description = "根据ID获取数据组件的详细信息")
    public Result<DataComponent> getComponentById(
            @Parameter(description = "组件ID") @PathVariable Long id) {
        
        DataComponent component = dataComponentService.getById(id);
        if (component == null) {
            return Result.error("数据组件不存在");
        }
        return Result.success(component);
    }

    @PostMapping
    @Operation(summary = "创建数据组件", description = "创建新的数据组件")
    public Result<DataComponent> createComponent(
            @Valid @RequestBody CreateComponentRequest request) {
        
        try {
            boolean success = dataComponentService.createComponent(request.getComponent(), request.getFields());
            if (success) {
                return Result.success(request.getComponent());
            } else {
                return Result.error("创建数据组件失败");
            }
        } catch (Exception e) {
            log.error("创建数据组件失败", e);
            return Result.error("创建数据组件失败: " + e.getMessage());
        }
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新数据组件", description = "更新数据组件信息")
    public Result<DataComponent> updateComponent(
            @Parameter(description = "组件ID") @PathVariable Long id,
            @Valid @RequestBody UpdateComponentRequest request) {
        
        try {
            request.getComponent().setId(id);
            boolean success = dataComponentService.updateComponent(request.getComponent(), request.getFields());
            if (success) {
                return Result.success(request.getComponent());
            } else {
                return Result.error("更新数据组件失败");
            }
        } catch (Exception e) {
            log.error("更新数据组件失败", e);
            return Result.error("更新数据组件失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除数据组件", description = "删除指定的数据组件")
    public Result<Void> deleteComponent(
            @Parameter(description = "组件ID") @PathVariable Long id) {
        
        try {
            boolean success = dataComponentService.deleteComponent(id);
            if (success) {
                return Result.success();
            } else {
                return Result.error("删除数据组件失败");
            }
        } catch (Exception e) {
            log.error("删除数据组件失败", e);
            return Result.error("删除数据组件失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}/fields")
    @Operation(summary = "获取组件字段配置", description = "获取指定组件的字段配置列表")
    public Result<List<DataComponentField>> getComponentFields(
            @Parameter(description = "组件ID") @PathVariable Long id) {
        
        List<DataComponentField> fields = dataComponentFieldService.getFieldsByComponentId(id);
        return Result.success(fields);
    }

    @PutMapping("/{id}/fields")
    @Operation(summary = "更新组件字段配置", description = "更新指定组件的字段配置")
    public Result<Void> updateComponentFields(
            @Parameter(description = "组件ID") @PathVariable Long id,
            @Valid @RequestBody List<DataComponentField> fields) {
        
        try {
            // 先删除原有字段配置
            dataComponentFieldService.deleteFieldsByComponentId(id);
            
            // 保存新的字段配置
            boolean success = dataComponentFieldService.saveFields(id, fields);
            if (success) {
                return Result.success();
            } else {
                return Result.error("更新字段配置失败");
            }
        } catch (Exception e) {
            log.error("更新字段配置失败", e);
            return Result.error("更新字段配置失败: " + e.getMessage());
        }
    }

    @PostMapping("/{id}/fields/generate")
    @Operation(summary = "自动生成字段配置", description = "根据数据源自动生成字段配置")
    public Result<List<DataComponentField>> generateFields(
            @Parameter(description = "组件ID") @PathVariable Long id,
            @RequestParam String dataSourceConfig) {
        
        try {
            List<DataComponentField> fields = dataComponentFieldService.generateFieldsFromDataSource(id, dataSourceConfig);
            return Result.success(fields);
        } catch (Exception e) {
            log.error("自动生成字段配置失败", e);
            return Result.error("自动生成字段配置失败: " + e.getMessage());
        }
    }

    @PostMapping("/{id}/test-datasource")
    @Operation(summary = "测试数据源连接", description = "测试数据组件的数据源连接是否正常")
    public Result<Map<String, Object>> testDataSource(
            @Parameter(description = "组件ID") @PathVariable Long id) {
        
        try {
            DataComponent component = dataComponentService.getById(id);
            if (component == null) {
                return Result.error("数据组件不存在");
            }
            
            Map<String, Object> result = dataComponentService.testDataSource(component);
            return Result.success(result);
        } catch (Exception e) {
            log.error("测试数据源失败", e);
            return Result.error("测试数据源失败: " + e.getMessage());
        }
    }

    @PostMapping("/test-datasource")
    @Operation(summary = "测试数据源连接（预览）", description = "在保存前测试数据源连接")
    public Result<Map<String, Object>> previewTestDataSource(
            @Valid @RequestBody DataComponent component) {
        
        try {
            Map<String, Object> result = dataComponentService.testDataSource(component);
            return Result.success(result);
        } catch (Exception e) {
            log.error("预览测试数据源失败", e);
            return Result.error("预览测试数据源失败: " + e.getMessage());
        }
    }

    @PostMapping("/{id}/query")
    @Operation(summary = "执行组件查询", description = "执行数据组件的数据查询")
    public Result<Map<String, Object>> executeQuery(
            @Parameter(description = "组件ID") @PathVariable Long id,
            @RequestBody(required = false) Map<String, Object> params) {
        
        try {
            if (params == null) {
                params = Map.of();
            }
            
            Map<String, Object> result = dataComponentService.executeQuery(id, params);
            return Result.success(result);
        } catch (Exception e) {
            log.error("执行组件查询失败", e);
            return Result.error("执行组件查询失败: " + e.getMessage());
        }
    }

    @PostMapping("/preview")
    @Operation(summary = "预览组件数据", description = "预览数据组件的查询结果")
    public Result<Map<String, Object>> previewData(
            @Valid @RequestBody PreviewRequest request) {
        
        try {
            Map<String, Object> params = request.getParams() != null ? request.getParams() : Map.of();
            Map<String, Object> result = dataComponentService.previewData(
                request.getComponent(), 
                request.getFields(), 
                params
            );
            return Result.success(result);
        } catch (Exception e) {
            log.error("预览组件数据失败", e);
            return Result.error("预览组件数据失败: " + e.getMessage());
        }
    }

    @PostMapping("/{id}/refresh-cache")
    @Operation(summary = "刷新组件缓存", description = "清除并刷新组件的缓存数据")
    public Result<Void> refreshCache(
            @Parameter(description = "组件ID") @PathVariable Long id) {
        
        try {
            boolean success = dataComponentService.refreshCache(id);
            if (success) {
                return Result.success();
            } else {
                return Result.error("刷新缓存失败");
            }
        } catch (Exception e) {
            log.error("刷新缓存失败", e);
            return Result.error("刷新缓存失败: " + e.getMessage());
        }
    }

    @PostMapping("/{id}/copy")
    @Operation(summary = "复制数据组件", description = "复制现有的数据组件")
    public Result<DataComponent> copyComponent(
            @Parameter(description = "源组件ID") @PathVariable Long id,
            @RequestParam String newName) {
        
        try {
            DataComponent newComponent = dataComponentService.copyComponent(id, newName);
            return Result.success(newComponent);
        } catch (Exception e) {
            log.error("复制数据组件失败", e);
            return Result.error("复制数据组件失败: " + e.getMessage());
        }
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取组件统计信息", description = "获取数据组件的统计信息")
    public Result<Map<String, Object>> getStatistics() {
        try {
            Map<String, Object> statistics = dataComponentService.getStatistics();
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取统计信息失败", e);
            return Result.error("获取统计信息失败: " + e.getMessage());
        }
    }

    @GetMapping("/types/{type}")
    @Operation(summary = "按类型查询组件", description = "根据组件类型查询组件列表")
    public Result<List<DataComponent>> getComponentsByType(
            @Parameter(description = "组件类型") @PathVariable String type) {
        
        try {
            List<DataComponent> components = dataComponentService.getComponentsByType(type);
            return Result.success(components);
        } catch (Exception e) {
            log.error("按类型查询组件失败", e);
            return Result.error("按类型查询组件失败: " + e.getMessage());
        }
    }

    // 内部类定义请求对象

    public static class CreateComponentRequest {
        private DataComponent component;
        private List<DataComponentField> fields;
        
        // getters and setters
        public DataComponent getComponent() { return component; }
        public void setComponent(DataComponent component) { this.component = component; }
        public List<DataComponentField> getFields() { return fields; }
        public void setFields(List<DataComponentField> fields) { this.fields = fields; }
    }

    public static class UpdateComponentRequest {
        private DataComponent component;
        private List<DataComponentField> fields;
        
        // getters and setters
        public DataComponent getComponent() { return component; }
        public void setComponent(DataComponent component) { this.component = component; }
        public List<DataComponentField> getFields() { return fields; }
        public void setFields(List<DataComponentField> fields) { this.fields = fields; }
    }

    public static class PreviewRequest {
        private DataComponent component;
        private List<DataComponentField> fields;
        private Map<String, Object> params;
        
        // getters and setters
        public DataComponent getComponent() { return component; }
        public void setComponent(DataComponent component) { this.component = component; }
        public List<DataComponentField> getFields() { return fields; }
        public void setFields(List<DataComponentField> fields) { this.fields = fields; }
        public Map<String, Object> getParams() { return params; }
        public void setParams(Map<String, Object> params) { this.params = params; }
    }
}